home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / IFF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-21  |  13.4 KB  |  601 lines

  1. /****************************************************************************
  2. *                   iff.c
  3. *
  4. *  This file implements a simple IFF format file reader.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "povproto.h"
  26. #include "iff.h"
  27. #include "povray.h"
  28.  
  29.  
  30.  
  31. /*****************************************************************************
  32. * Local preprocessor defines
  33. ******************************************************************************/
  34.  
  35. #define FORM 0x464f524dL
  36. #define ILBM 0x494c424dL
  37. #define BMHD 0x424d4844L
  38. #define CAMG 0x43414d47L
  39. #define CMAP 0x434d4150L
  40. #define BODY 0x424f4459L
  41. #define CMPNONE 0
  42.  
  43. #define HAM 0x800
  44.  
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local typedefs
  49. ******************************************************************************/
  50.  
  51.  
  52.  
  53. /*****************************************************************************
  54. * Local variables
  55. ******************************************************************************/
  56.  
  57. static IMAGE_COLOUR *iff_colour_map;
  58. static int colourmap_size;
  59. static CHUNK_HEADER Chunk_Header;
  60.  
  61.  
  62.  
  63. /*****************************************************************************
  64. * Static functions
  65. ******************************************************************************/
  66.  
  67. static void iff_error PARAMS((void));
  68. static int read_byte PARAMS((FILE * f));
  69. static int read_word PARAMS((FILE * f));
  70. static long read_long PARAMS((FILE * f));
  71. static void Read_Chunk_Header PARAMS((FILE * f, CHUNK_HEADER * dest));
  72.  
  73.  
  74.  
  75. /*****************************************************************************
  76. *
  77. * FUNCTION
  78. *
  79. * INPUT
  80. *
  81. * OUTPUT
  82. *
  83. * RETURNS
  84. *
  85. * AUTHOR
  86. *
  87. *   POV-Ray Team
  88. *
  89. * DESCRIPTION
  90. *
  91. *   -
  92. *
  93. * CHANGES
  94. *
  95. *   -
  96. *
  97. ******************************************************************************/
  98.  
  99. static void iff_error()
  100. {
  101.   Error("Error reading IFF image.\n");
  102. }
  103.  
  104.  
  105.  
  106. /*****************************************************************************
  107. *
  108. * FUNCTION
  109. *
  110. * INPUT
  111. *
  112. * OUTPUT
  113. *
  114. * RETURNS
  115. *
  116. * AUTHOR
  117. *
  118. *   POV-Ray Team
  119. *
  120. * DESCRIPTION
  121. *
  122. *   -
  123. *
  124. * CHANGES
  125. *
  126. *   -
  127. *
  128. ******************************************************************************/
  129.  
  130. static int read_byte(f)
  131. FILE *f;
  132. {
  133.   int c;
  134.  
  135.   if ((c = getc(f)) == EOF)
  136.   {
  137.     iff_error();
  138.   }
  139.  
  140.   return (c);
  141. }
  142.  
  143.  
  144.  
  145. /*****************************************************************************
  146. *
  147. * FUNCTION
  148. *
  149. * INPUT
  150. *
  151. * OUTPUT
  152. *
  153. * RETURNS
  154. *
  155. * AUTHOR
  156. *
  157. *   POV-Ray Team
  158. *
  159. * DESCRIPTION
  160. *
  161. *   -
  162. *
  163. * CHANGES
  164. *
  165. *   -
  166. *
  167. ******************************************************************************/
  168.  
  169. static int read_word(f)
  170. FILE *f;
  171. {
  172.   int result;
  173.  
  174.   result = read_byte(f) * 256;
  175.  
  176.   result += read_byte(f);
  177.  
  178.   return (result);
  179. }
  180.  
  181.  
  182.  
  183. /*****************************************************************************
  184. *
  185. * FUNCTION
  186. *
  187. * INPUT
  188. *
  189. * OUTPUT
  190. *
  191. * RETURNS
  192. *
  193. * AUTHOR
  194. *
  195. *   POV-Ray Team
  196. *
  197. * DESCRIPTION
  198. *
  199. *   -
  200. *
  201. * CHANGES
  202. *
  203. *   -
  204. *
  205. ******************************************************************************/
  206.  
  207. static long read_long(f)
  208. FILE *f;
  209. {
  210.   int i;
  211.   long result;
  212.  
  213.   result = 0;
  214.  
  215.   for (i = 0; i < 4; i++)
  216.   {
  217.     result = result * 256 + read_byte(f);
  218.   }
  219.  
  220.   return (result);
  221. }
  222.  
  223.  
  224.  
  225. /*****************************************************************************
  226. *
  227. * FUNCTION
  228. *
  229. * INPUT
  230. *
  231. * OUTPUT
  232. *
  233. * RETURNS
  234. *
  235. * AUTHOR
  236. *
  237. *   POV-Ray Team
  238. *
  239. * DESCRIPTION
  240. *
  241. *   -
  242. *
  243. * CHANGES
  244. *
  245. *   -
  246. *
  247. ******************************************************************************/
  248.  
  249. static void Read_Chunk_Header(f, dest)
  250. FILE *f;
  251. CHUNK_HEADER *dest;
  252. {
  253.   dest->name = read_long(f);
  254.   dest->size = read_long(f);
  255. }
  256.  
  257.  
  258.  
  259. /*****************************************************************************
  260. *
  261. * FUNCTION
  262. *
  263. * INPUT
  264. *
  265. * OUTPUT
  266. *
  267. * RETURNS
  268. *
  269. * AUTHOR
  270. *
  271. *   POV-Ray Team
  272. *
  273. * DESCRIPTION
  274. *
  275. *   -
  276. *
  277. * CHANGES
  278. *
  279. *   -
  280. *
  281. ******************************************************************************/
  282.  
  283. void Read_Iff_Image(Image, filename)
  284. IMAGE *Image;
  285. char *filename;
  286. {
  287.   unsigned char **row_bytes;
  288.   int c, i, j, k, nBytes, nPlanes = 0, compression = 0;
  289.   int mask, byte_index, count, viewmodes;
  290.   int Previous_Red, Previous_Green, Previous_Blue;
  291.   unsigned long creg;
  292.   FILE *f;
  293.   IMAGE_LINE *line;
  294.  
  295.   if ((f = Locate_File(filename, READ_FILE_STRING, ".iff", ".IFF",TRUE)) == NULL)
  296.   {
  297.     Error("Error opening IFF image.\n");
  298.   }
  299.  
  300.   Previous_Red = Previous_Green = Previous_Blue = 0;
  301.  
  302.   viewmodes = 0;
  303.  
  304.   iff_colour_map = NULL;
  305.  
  306.   while (1)
  307.   {
  308.     Read_Chunk_Header(f, &Chunk_Header);
  309.  
  310.     switch (IFF_SWITCH_CAST Chunk_Header.name)
  311.     {
  312.       case FORM:
  313.  
  314.         if (read_long(f) != ILBM)
  315.         {
  316.           iff_error();
  317.         }
  318.  
  319.         break;
  320.  
  321.       case BMHD:
  322.  
  323.         Image->iwidth = read_word(f);
  324.         Image->iheight = read_word(f);
  325.  
  326.         Image->width = (DBL)Image->iwidth;
  327.         Image->height = (DBL)Image->iheight;
  328.  
  329.         read_word(f); /* x position ignored */
  330.         read_word(f); /* y position ignored */
  331.  
  332.         nPlanes = read_byte(f);
  333.  
  334.         colourmap_size = 1 << nPlanes;
  335.  
  336.         read_byte(f); /* masking ignored */
  337.  
  338.         compression = read_byte(f); /* masking ignored */
  339.  
  340.         read_byte(f); /* pad */
  341.         read_word(f); /* Transparent colour ignored */
  342.         read_word(f); /* Aspect ratio ignored */
  343.         read_word(f); /* page width ignored */
  344.         read_word(f); /* page height ignored */
  345.  
  346.         break;
  347.  
  348.       case CAMG:
  349.  
  350.         viewmodes = (int)read_long(f);  /* Viewmodes */
  351.  
  352.         if (viewmodes & HAM)
  353.         {
  354.           colourmap_size = 16;
  355.         }
  356.  
  357.         break;
  358.  
  359.       case CMAP:
  360.  
  361.         colourmap_size = (int)Chunk_Header.size / 3;
  362.  
  363.         iff_colour_map = (IMAGE_COLOUR *)POV_MALLOC(sizeof(IMAGE_COLOUR) * colourmap_size, "IFF color map");
  364.  
  365.         for (i = 0; i < colourmap_size; i++)
  366.         {
  367.           iff_colour_map[i].Red = read_byte(f);
  368.           iff_colour_map[i].Green = read_byte(f);
  369.           iff_colour_map[i].Blue = read_byte(f);
  370.           iff_colour_map[i].Filter = 0;
  371.           iff_colour_map[i].Transmit = 0;
  372.         }
  373.  
  374.         Previous_Red = iff_colour_map[0].Red;
  375.         Previous_Green = iff_colour_map[0].Green;
  376.         Previous_Blue = iff_colour_map[0].Blue;
  377.  
  378.         for (i = colourmap_size * 3; (long)i < Chunk_Header.size; i++)
  379.         {
  380.           read_byte(f);
  381.         }
  382.  
  383.         break;
  384.  
  385.       case BODY:
  386.  
  387.         if ((iff_colour_map == NULL) || (viewmodes & HAM))
  388.         {
  389.           Image->Colour_Map_Size = 0;
  390.           Image->Colour_Map = NULL;
  391.         }
  392.         else
  393.         {
  394.           Image->Colour_Map_Size = colourmap_size;
  395.           Image->Colour_Map = iff_colour_map;
  396.         }
  397.  
  398.         row_bytes = (unsigned char **)POV_MALLOC((size_t) (4 * nPlanes), "IFF decoder line");
  399.  
  400.         for (i = 0; i < nPlanes; i++)
  401.         {
  402.           row_bytes[i] = (unsigned char *)POV_MALLOC((size_t) (((Image->iwidth + 15) / 16) * 2), "IFF decoder line");
  403.         }
  404.  
  405.         if (Image->Colour_Map == NULL)
  406.         {
  407.           Image->data.rgb_lines = (IMAGE_LINE *)POV_MALLOC(Image->iheight * sizeof(IMAGE_LINE), "IFF image");
  408.         }
  409.         else
  410.         {
  411.           Image->data.map_lines = (unsigned char **)POV_MALLOC(Image->iheight * sizeof(unsigned char *), "IFF image");
  412.         }
  413.  
  414.         for (i = 0; i < Image->iheight; i++)
  415.         {
  416.           if (Image->Colour_Map == NULL)
  417.           {
  418.             Image->data.rgb_lines[i].red = (unsigned char *)POV_MALLOC((size_t) Image->iwidth, "IFF image line");
  419.             Image->data.rgb_lines[i].green = (unsigned char *)POV_MALLOC((size_t) Image->iwidth, "IFF image line");
  420.             Image->data.rgb_lines[i].blue = (unsigned char *)POV_MALLOC((size_t) Image->iwidth, "IFF image line");
  421.           }
  422.           else
  423.           {
  424.             Image->data.map_lines[i] = (unsigned char *)POV_MALLOC(Image->iwidth * sizeof(unsigned char), "IFF image line");
  425.           }
  426.  
  427.           for (j = 0; j < nPlanes; j++)
  428.           {
  429.             if (compression == CMPNONE)
  430.             {
  431.               for (k = 0; k < (((Image->iwidth + 15) / 16) * 2); k++)
  432.               {
  433.                 row_bytes[j][k] = (unsigned char)read_byte(f);
  434.               }
  435.  
  436.               if ((k & 1) != 0)
  437.               {
  438.                 read_byte(f);
  439.               }
  440.             }
  441.             else
  442.             {
  443.               nBytes = 0;
  444.  
  445.               while (nBytes != ((Image->iwidth + 15) / 16) * 2)
  446.               {
  447.                 c = read_byte(f);
  448.  
  449.                 if ((c >= 0) && (c <= 127))
  450.                 {
  451.                   for (k = 0; k <= c; k++)
  452.                   {
  453.                     row_bytes[j][nBytes++] = (unsigned char)read_byte(f);
  454.                   }
  455.                 }
  456.                 else
  457.                 {
  458.                   if ((c >= 129) && (c <= 255))
  459.                   {
  460.                     count = 257 - c;
  461.  
  462.                     c = read_byte(f);
  463.  
  464.                     for (k = 0; k < count; k++)
  465.                     {
  466.                       row_bytes[j][nBytes++] = (unsigned char)c;
  467.                     }
  468.                   }
  469.                 }
  470.               }
  471.             }
  472.           }
  473.  
  474.           mask = 0x80;
  475.  
  476.           byte_index = 0;
  477.  
  478.           for (j = 0; j < Image->iwidth; j++)
  479.           {
  480.             creg = 0;
  481.  
  482.             for (k = nPlanes - 1; k >= 0; k--)
  483.             {
  484.               if (row_bytes[k][byte_index] & mask)
  485.               {
  486.                 creg = creg * 2 + 1;
  487.               }
  488.               else
  489.               {
  490.                 creg *= 2;
  491.               }
  492.             }
  493.  
  494.             if (viewmodes & HAM)
  495.             {
  496.               line = &Image->data.rgb_lines[i];
  497.  
  498.               switch ((int)(creg >> 4))
  499.               {
  500.                 case 0:
  501.  
  502.                   Previous_Red = line->red[j] = (unsigned char)iff_colour_map[creg].Red;
  503.                   Previous_Green = line->green[j] = (unsigned char)iff_colour_map[creg].Green;
  504.                   Previous_Blue = line->blue[j] = (unsigned char)iff_colour_map[creg].Blue;
  505.  
  506.                   break;
  507.  
  508.                 case 1:
  509.  
  510.                   line->red[j] = (unsigned char)Previous_Red;
  511.                   line->green[j] = (unsigned char)Previous_Green;
  512.                   line->blue[j] = (unsigned char)(((creg & 0xf) << 4) + (creg & 0xf));
  513.  
  514.                   Previous_Blue = (int)line->blue[j];
  515.  
  516.                   break;
  517.  
  518.                 case 2:
  519.  
  520.                   line->red[j] = (unsigned char)(((creg & 0xf) << 4) + (creg & 0xf));
  521.  
  522.                   Previous_Red = (int)line->red[j];
  523.  
  524.                   line->green[j] = (unsigned char)Previous_Green;
  525.                   line->blue[j] = (unsigned char)Previous_Blue;
  526.  
  527.                   break;
  528.  
  529.                 case 3:
  530.  
  531.                   line->red[j] = (unsigned char)Previous_Red;
  532.                   line->green[j] = (unsigned char)(((creg & 0xf) << 4) + (creg & 0xf));
  533.  
  534.                   Previous_Green = (int)line->green[j];
  535.  
  536.                   line->blue[j] = (unsigned char)Previous_Blue;
  537.  
  538.                   break;
  539.               }
  540.             }
  541.             else
  542.             {
  543.               if (nPlanes == 24)
  544.               {
  545.                 line = &Image->data.rgb_lines[i];
  546.  
  547.                 line->red[j] = (unsigned char)((creg >> 16) & 0xFF);
  548.                 line->green[j] = (unsigned char)((creg >> 8) & 0xFF);
  549.                 line->blue[j] = (unsigned char)(creg & 0xFF);
  550.               }
  551.               else
  552.               {
  553.                 if (creg > (unsigned long)Image->Colour_Map_Size)
  554.                 {
  555.                   Error("Error - IFF color out of range in image.\n");
  556.                 }
  557.  
  558.                 Image->data.map_lines[i][j] = (char)creg;
  559.               }
  560.             }
  561.  
  562.             mask >>= 1;
  563.  
  564.             if (mask == 0)
  565.             {
  566.               mask = 0x80;
  567.  
  568.               byte_index++;
  569.             }
  570.           }
  571.         }
  572.  
  573.         if (row_bytes != NULL)
  574.         {
  575.           for (i = 0; i < nPlanes; i++)
  576.           {
  577.             POV_FREE(row_bytes[i]);
  578.           }
  579.  
  580.           POV_FREE(row_bytes);
  581.         }
  582.  
  583.         fclose(f);
  584.  
  585.         return;
  586.  
  587.       default:
  588.  
  589.         for (i = 0; (long)i < Chunk_Header.size; i++)
  590.         {
  591.           if (getc(f) == EOF)
  592.           {
  593.             iff_error();
  594.           }
  595.         }
  596.  
  597.         break;
  598.     }
  599.   }
  600. }
  601.